package com.ken.concurrencystudy.example;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @author liushiyu@changingedu.com
 * @date 6/6/2020 17:06
 */
@Slf4j
public class VolatileExample {

    int x= 0;
    volatile boolean v = false;

    public void writer(){
        /**
         * Happens-Before原则一（程序的顺序性规则）：在同一个线程内，前一个操作Happens-Before于后一个操作
         * 也就是说 x=42的赋值操作，肯定比v=true赋值先行发生
         */
        x = 42;
        v = true;
    }

    public void reader(){
        /**
         * Happens-Before原则二（volatile变量规则）：对volatile修饰的变量的写操作Happens-Before于对该变量的读操作
         * Happens-Before原则三（传递性规则）：如果A Happens-Before B ，且B Happens-Before C，那么A Happens-Before C
         * 也就是说，如果下方的v==true成立，那么v=true;语句已经发生，而根据原则一，v=true;已经发生代表x=42;语句也已经发生，那么根据原则三，v==true成立，那么此时x的值肯定为42；
         */
        while (v== false){
            log.info("x:{}",x);
        }
        log.info("x:{}",x);
    }

    private static final int CORE_POOL_SIZE = 2;
    private static final int MAX_POOL_SIZE = 100;
    private static final int QUEUE_CAPACITY = 100;
    private static final Long KEEP_ALIVE_TIME = 1L;

    public static void main(String[] args) throws InterruptedException {
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(CORE_POOL_SIZE
                ,MAX_POOL_SIZE
                ,KEEP_ALIVE_TIME, TimeUnit.SECONDS
                ,new ArrayBlockingQueue<Runnable>(QUEUE_CAPACITY));
        VolatileExample volatileExample = new VolatileExample();
        threadPoolExecutor.execute(new Runnable() {
            @Override
            public void run() {
                volatileExample.reader();
            }
        });
        Thread.sleep(1000);
        threadPoolExecutor.execute(new Runnable() {
            @Override
            public void run() {
                volatileExample.writer();
            }
        });
        threadPoolExecutor.shutdown();
        while (!threadPoolExecutor.isShutdown()){

        }
        log.info("hello world!");
    }
}
